//    Copyright (C) Kherty.  All rights reserved.
using System;
using System.Collections.Generic;
using System.Reflection;
using OpenLS.Spreadsheet.Extensibility;

namespace OpenLS.Spreadsheet.Functions
{
    public class FunctionManager
    {
        public static void AddAddIn(Assembly assembly)
        {
            AddIn a = new AddIn(assembly);
            foreach (var function in a.GetFunctions())
            {
                addInFunctions.Add(function.Name.ToUpper(), function);
            }
        }
        static readonly Dictionary<string, Function> addInFunctions = new Dictionary<string, Function>();

        static internal Function GetFunction(string name, SpreadsheetContext context)
        {
            string upperName = name.ToUpper();
            foreach (AddIn addin in context.AddIns)
            {
                Function result;
                if (addin.TryGetFunction(upperName, out result))
                    return result;
            }
            return new UnknownFunction(name);
            //\\Function result;
        }
        static internal IEnumerable<AddInFunction> GetFunctions(SpreadsheetContext context)
        {
            foreach (AddIn addin in context.AddIns)
            {
                foreach (var function in addin.GetFunctions())
                {
                    yield return function;
                }
            }
            
        }
        public static IEnumerable<Function> LookupReferenceFunctions
        {
            get
            {
                return GetAllFunctions("LookupFunctions");
            }
        }
        public static IEnumerable<Function> FinancialFunctions
        {
            get
            {
                return GetAllFunctions("FinancialFunctions");
            }
        }
        static readonly List<Function> basicFunctions = new List<Function>();
        public static List<Function> BasicFunctions
        {
            get
            {
                return basicFunctions;
            }
        }
        public static IEnumerable<Function> InformationFunctions
        {
            get
            {
                return GetAllFunctions("InformationFunctions");
            }
        }
        public static IEnumerable<Function> MathFunctions
        {
            get
            {
                return GetAllFunctions("MathFunctions");
            }
        }
        public static IEnumerable<Function> DateTimeFunctions
        {
            get
            {
                return GetAllFunctions("DateFunctions");
            }
        }
        public static IEnumerable<Function> StatisticalFunctions
        {
            get
            {
                return GetAllFunctions("StatisticalFunctions");
            }
        }
        public static IEnumerable<Function> EngineeringFunctions
        {
            get
            {
                return GetAllFunctions("EngineeringFunctions");
            }
        }
        static IEnumerable<Function> GetAllFunctions(string typeName)
        {
            foreach (Function fn in addInFunctions.Values)
            {
                if (fn is AddInFunction)
                {
                    AddInFunction aif = (AddInFunction)fn;
                    Type t = aif.Method.DeclaringType;
                    if (t.Name == typeName)
                        yield return aif;
                }
            }
        }
        public static IEnumerable<Function> LogicalFunctions
        {
            get
            {
                return GetAllFunctions("LogicalFunctions");
            }
        }
        public static IEnumerable<Function> TextFunctions
        {
            get
            {
                return GetAllFunctions("TextFunctions");
            }
        }
    }
}
